// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.iso;

import gnu.trove.map.hash.THashMap;
import java.util.ArrayList;
import se.krka.kahlua.j2se.KahluaTableImpl;
import se.krka.kahlua.vm.KahluaTable;
import se.krka.kahlua.vm.KahluaTableIterator;
import zombie.core.Rand;
import zombie.core.properties.PropertyContainer;
import zombie.inventory.InventoryItemFactory;
import zombie.iso.SpriteDetails.IsoFlagType;
import zombie.iso.areas.isoregion.IsoRegions;
import zombie.iso.objects.IsoThumpable;
import zombie.iso.sprite.IsoSprite;
import zombie.iso.sprite.IsoSpriteManager;
import zombie.network.GameServer;
import zombie.util.list.PZArrayUtil;
import zombie.vehicles.PolygonalMap2;

public class BrokenFences {
    private static final BrokenFences instance = new BrokenFences();
    private final THashMap<String, BrokenFences.Tile> s_unbrokenMap = new THashMap<>();
    private final THashMap<String, BrokenFences.Tile> s_brokenLeftMap = new THashMap<>();
    private final THashMap<String, BrokenFences.Tile> s_brokenRightMap = new THashMap<>();
    private final THashMap<String, BrokenFences.Tile> s_allMap = new THashMap<>();

    public static BrokenFences getInstance() {
        return instance;
    }

    private ArrayList<String> tableToTiles(KahluaTableImpl kahluaTableImpl) {
        if (kahluaTableImpl == null) {
            return null;
        } else {
            ArrayList arrayList = null;

            for (KahluaTableIterator kahluaTableIterator = kahluaTableImpl.iterator();
                kahluaTableIterator.advance();
                arrayList.add(kahluaTableIterator.getValue().toString())
            ) {
                if (arrayList == null) {
                    arrayList = new ArrayList();
                }
            }

            return arrayList;
        }
    }

    private ArrayList<String> tableToTiles(KahluaTable kahluaTable, String string) {
        return this.tableToTiles((KahluaTableImpl)kahluaTable.rawget(string));
    }

    public void addBrokenTiles(KahluaTableImpl kahluaTableImpl0) {
        KahluaTableIterator kahluaTableIterator = kahluaTableImpl0.iterator();

        while (kahluaTableIterator.advance()) {
            String string = kahluaTableIterator.getKey().toString();
            if (!"VERSION".equalsIgnoreCase(string)) {
                KahluaTableImpl kahluaTableImpl1 = (KahluaTableImpl)kahluaTableIterator.getValue();
                BrokenFences.Tile tile = new BrokenFences.Tile();
                tile.self = this.tableToTiles(kahluaTableImpl1, "self");
                tile.left = this.tableToTiles(kahluaTableImpl1, "left");
                tile.right = this.tableToTiles(kahluaTableImpl1, "right");
                this.s_unbrokenMap.put(string, tile);
                PZArrayUtil.forEach(tile.left, stringx -> this.s_brokenLeftMap.put(stringx, tile));
                PZArrayUtil.forEach(tile.right, stringx -> this.s_brokenRightMap.put(stringx, tile));
            }
        }

        this.s_allMap.putAll(this.s_unbrokenMap);
        this.s_allMap.putAll(this.s_brokenLeftMap);
        this.s_allMap.putAll(this.s_brokenRightMap);
    }

    public void addDebrisTiles(KahluaTableImpl kahluaTableImpl0) {
        KahluaTableIterator kahluaTableIterator = kahluaTableImpl0.iterator();

        while (kahluaTableIterator.advance()) {
            String string = kahluaTableIterator.getKey().toString();
            if (!"VERSION".equalsIgnoreCase(string)) {
                KahluaTableImpl kahluaTableImpl1 = (KahluaTableImpl)kahluaTableIterator.getValue();
                BrokenFences.Tile tile = this.s_unbrokenMap.get(string);
                if (tile == null) {
                    throw new IllegalArgumentException("addDebrisTiles() with unknown tile");
                }

                tile.debrisN = this.tableToTiles(kahluaTableImpl1, "north");
                tile.debrisS = this.tableToTiles(kahluaTableImpl1, "south");
                tile.debrisW = this.tableToTiles(kahluaTableImpl1, "west");
                tile.debrisE = this.tableToTiles(kahluaTableImpl1, "east");
            }
        }
    }

    public void setDestroyed(IsoObject obj) {
        obj.RemoveAttachedAnims();
        obj.getSquare().removeBlood(false, true);
        this.updateSprite(obj, true, true);
    }

    public void setDamagedLeft(IsoObject obj) {
        this.updateSprite(obj, true, false);
    }

    public void setDamagedRight(IsoObject obj) {
        this.updateSprite(obj, false, true);
    }

    public void updateSprite(IsoObject obj, boolean brokenLeft, boolean brokenRight) {
        if (this.isBreakableObject(obj)) {
            BrokenFences.Tile tile = this.s_allMap.get(obj.sprite.name);
            String string = null;
            if (brokenLeft && brokenRight) {
                string = tile.pickRandom(tile.self);
            } else if (brokenLeft) {
                string = tile.pickRandom(tile.left);
            } else if (brokenRight) {
                string = tile.pickRandom(tile.right);
            }

            if (string != null) {
                IsoSprite isoSprite = IsoSpriteManager.instance.getSprite(string);
                isoSprite.name = string;
                obj.setSprite(isoSprite);
                obj.transmitUpdatedSprite();
                obj.getSquare().RecalcAllWithNeighbours(true);
                zombie.MapCollisionData.instance.squareChanged(obj.getSquare());
                PolygonalMap2.instance.squareChanged(obj.getSquare());
                IsoRegions.squareChanged(obj.getSquare());
            }
        }
    }

    private boolean isNW(IsoObject isoObject) {
        PropertyContainer propertyContainer = isoObject.getProperties();
        return propertyContainer.Is(IsoFlagType.collideN) && propertyContainer.Is(IsoFlagType.collideW);
    }

    private void damageAdjacent(IsoGridSquare isoGridSquare1, IsoDirections isoDirections0, IsoDirections isoDirections1) {
        IsoGridSquare isoGridSquare0 = isoGridSquare1.getAdjacentSquare(isoDirections0);
        if (isoGridSquare0 != null) {
            boolean boolean0 = isoDirections0 == IsoDirections.W || isoDirections0 == IsoDirections.E;
            IsoObject isoObject = this.getBreakableObject(isoGridSquare0, boolean0);
            if (isoObject != null) {
                boolean boolean1 = isoDirections0 == IsoDirections.N || isoDirections0 == IsoDirections.E;
                boolean boolean2 = isoDirections0 == IsoDirections.S || isoDirections0 == IsoDirections.W;
                if (!this.isNW(isoObject) || isoDirections0 != IsoDirections.S && isoDirections0 != IsoDirections.E) {
                    if (boolean1 && this.isBrokenRight(isoObject)) {
                        this.destroyFence(isoObject, isoDirections1);
                    } else if (boolean2 && this.isBrokenLeft(isoObject)) {
                        this.destroyFence(isoObject, isoDirections1);
                    } else {
                        this.updateSprite(isoObject, boolean1, boolean2);
                    }
                }
            }
        }
    }

    public void destroyFence(IsoObject obj, IsoDirections dir) {
        if (this.isBreakableObject(obj)) {
            IsoGridSquare isoGridSquare = obj.getSquare();
            if (GameServer.bServer) {
                GameServer.PlayWorldSoundServer("BreakObject", false, isoGridSquare, 1.0F, 20.0F, 1.0F, true);
            } else {
                zombie.SoundManager.instance.PlayWorldSound("BreakObject", isoGridSquare, 1.0F, 20.0F, 1.0F, true);
            }

            boolean boolean0 = obj.getProperties().Is(IsoFlagType.collideN);
            boolean boolean1 = obj.getProperties().Is(IsoFlagType.collideW);
            if (obj instanceof IsoThumpable) {
                IsoObject isoObject = IsoObject.getNew();
                isoObject.setSquare(isoGridSquare);
                isoObject.setSprite(obj.getSprite());
                int _int = obj.getObjectIndex();
                isoGridSquare.transmitRemoveItemFromSquare(obj);
                isoGridSquare.transmitAddObjectToSquare(isoObject, _int);
                obj = isoObject;
            }

            this.addDebrisObject(obj, dir);
            this.setDestroyed(obj);
            if (boolean0 && boolean1) {
                this.damageAdjacent(isoGridSquare, IsoDirections.S, dir);
                this.damageAdjacent(isoGridSquare, IsoDirections.E, dir);
            } else if (boolean0) {
                this.damageAdjacent(isoGridSquare, IsoDirections.W, dir);
                this.damageAdjacent(isoGridSquare, IsoDirections.E, dir);
            } else if (boolean1) {
                this.damageAdjacent(isoGridSquare, IsoDirections.N, dir);
                this.damageAdjacent(isoGridSquare, IsoDirections.S, dir);
            }

            isoGridSquare.RecalcAllWithNeighbours(true);
            zombie.MapCollisionData.instance.squareChanged(isoGridSquare);
            PolygonalMap2.instance.squareChanged(isoGridSquare);
            IsoRegions.squareChanged(isoGridSquare);
        }
    }

    private boolean isUnbroken(IsoObject isoObject) {
        return isoObject != null && isoObject.sprite != null && isoObject.sprite.name != null ? this.s_unbrokenMap.contains(isoObject.sprite.name) : false;
    }

    private boolean isBrokenLeft(IsoObject isoObject) {
        return isoObject != null && isoObject.sprite != null && isoObject.sprite.name != null ? this.s_brokenLeftMap.contains(isoObject.sprite.name) : false;
    }

    private boolean isBrokenRight(IsoObject isoObject) {
        return isoObject != null && isoObject.sprite != null && isoObject.sprite.name != null ? this.s_brokenRightMap.contains(isoObject.sprite.name) : false;
    }

    public boolean isBreakableObject(IsoObject obj) {
        return obj != null && obj.sprite != null && obj.sprite.name != null ? this.s_allMap.containsKey(obj.sprite.name) : false;
    }

    private IsoObject getBreakableObject(IsoGridSquare isoGridSquare, boolean _boolean) {
        for (int _int = 0; _int < isoGridSquare.Objects.size(); _int++) {
            IsoObject isoObject = isoGridSquare.Objects.get(_int);
            if (this.isBreakableObject(isoObject)
                && (_boolean && isoObject.getProperties().Is(IsoFlagType.collideN) || !_boolean && isoObject.getProperties().Is(IsoFlagType.collideW))) {
                return isoObject;
            }
        }

        return null;
    }

    private void addItems(IsoObject isoObject, IsoGridSquare isoGridSquare) {
        PropertyContainer propertyContainer = isoObject.getProperties();
        if (propertyContainer != null) {
            String string0 = propertyContainer.Val("Material");
            String string1 = propertyContainer.Val("Material2");
            String string2 = propertyContainer.Val("Material3");
            if ("Wood".equals(string0) || "Wood".equals(string1) || "Wood".equals(string2)) {
                isoGridSquare.AddWorldInventoryItem(InventoryItemFactory.CreateItem("Base.Plank"), Rand.Next(0.0F, 0.5F), Rand.Next(0.0F, 0.5F), 0.0F);
                if (Rand.NextBool(5)) {
                    isoGridSquare.AddWorldInventoryItem(InventoryItemFactory.CreateItem("Base.Plank"), Rand.Next(0.0F, 0.5F), Rand.Next(0.0F, 0.5F), 0.0F);
                }
            }

            if (("MetalBars".equals(string0) || "MetalBars".equals(string1) || "MetalBars".equals(string2)) && Rand.NextBool(2)) {
                isoGridSquare.AddWorldInventoryItem(InventoryItemFactory.CreateItem("Base.MetalBar"), Rand.Next(0.0F, 0.5F), Rand.Next(0.0F, 0.5F), 0.0F);
            }

            if (("MetalWire".equals(string0) || "MetalWire".equals(string1) || "MetalWire".equals(string2)) && Rand.NextBool(3)) {
                isoGridSquare.AddWorldInventoryItem(InventoryItemFactory.CreateItem("Base.Wire"), Rand.Next(0.0F, 0.5F), Rand.Next(0.0F, 0.5F), 0.0F);
            }

            if (("Nails".equals(string0) || "Nails".equals(string1) || "Nails".equals(string2)) && Rand.NextBool(2)) {
                isoGridSquare.AddWorldInventoryItem(InventoryItemFactory.CreateItem("Base.Nails"), Rand.Next(0.0F, 0.5F), Rand.Next(0.0F, 0.5F), 0.0F);
            }

            if (("Screws".equals(string0) || "Screws".equals(string1) || "Screws".equals(string2)) && Rand.NextBool(2)) {
                isoGridSquare.AddWorldInventoryItem(InventoryItemFactory.CreateItem("Base.Screws"), Rand.Next(0.0F, 0.5F), Rand.Next(0.0F, 0.5F), 0.0F);
            }
        }
    }

    private void addDebrisObject(IsoObject isoObject0, IsoDirections isoDirections) {
        if (this.isBreakableObject(isoObject0)) {
            BrokenFences.Tile tile = this.s_allMap.get(isoObject0.sprite.name);
            IsoGridSquare isoGridSquare = isoObject0.getSquare();
            String string;
            switch (isoDirections) {
                case N:
                    string = tile.pickRandom(tile.debrisN);
                    isoGridSquare = isoGridSquare.getAdjacentSquare(isoDirections);
                    break;
                case S:
                    string = tile.pickRandom(tile.debrisS);
                    break;
                case W:
                    string = tile.pickRandom(tile.debrisW);
                    isoGridSquare = isoGridSquare.getAdjacentSquare(isoDirections);
                    break;
                case E:
                    string = tile.pickRandom(tile.debrisE);
                    break;
                default:
                    throw new IllegalArgumentException("invalid direction");
            }

            if (string != null && isoGridSquare != null && isoGridSquare.TreatAsSolidFloor()) {
                IsoObject isoObject1 = IsoObject.getNew(isoGridSquare, string, null, false);
                isoGridSquare.transmitAddObjectToSquare(isoObject1, isoGridSquare == isoObject0.getSquare() ? isoObject0.getObjectIndex() : -1);
                this.addItems(isoObject0, isoGridSquare);
            }
        }
    }

    public void Reset() {
        this.s_unbrokenMap.clear();
        this.s_brokenLeftMap.clear();
        this.s_brokenRightMap.clear();
        this.s_allMap.clear();
    }

    private static final class Tile {
        ArrayList<String> self = null;
        ArrayList<String> left = null;
        ArrayList<String> right = null;
        ArrayList<String> debrisN = null;
        ArrayList<String> debrisS = null;
        ArrayList<String> debrisW = null;
        ArrayList<String> debrisE = null;

        String pickRandom(ArrayList<String> arrayList) {
            return arrayList == null ? null : PZArrayUtil.pickRandom(arrayList);
        }
    }
}
